﻿using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;

namespace SoftSource.Common
{
    /// <summary>
    /// These methods use expression trees instead of reflection to get property names.
    /// </summary>
    public static class ObjectReflection
    {
        public static string GetPropertyName<T>(
            Expression<Func<T, object>> propertyExpression)
        {
            MemberExpression memberExpression = ObjectReflection.GetMemberExpression(propertyExpression);

            var propertyInfo = memberExpression.Member as PropertyInfo;

            if (propertyInfo != null)
                return propertyInfo.Name ?? string.Empty;
            return string.Empty;
        }

        public static string GetPropertyName(
            Expression<Func<object>> propertyExpression)
        {
            MemberExpression memberExpression = ObjectReflection.GetMemberExpression(propertyExpression);

            var propertyInfo = memberExpression.Member as PropertyInfo;

            if (propertyInfo != null)
                return propertyInfo.Name ?? string.Empty;
            return string.Empty;
        }

        public static string GetMemberName(
            Expression<Func<object>> propertyExpression)
        {
            MemberExpression memberExpression = ObjectReflection.GetMemberExpression(propertyExpression);

            if (memberExpression.Member != null)
                return memberExpression.Member.Name ?? string.Empty;
            return string.Empty;
        }

        private static MemberExpression GetMemberExpression(Expression propertyExpression)
        {
            var lambda = propertyExpression as LambdaExpression;
            MemberExpression memberExpression = null;

            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = lambda.Body as UnaryExpression;
                memberExpression = unaryExpression.Operand as MemberExpression;
            }
            else
            {
                memberExpression = lambda.Body as MemberExpression;
            }

            return memberExpression;
        }
    }
}
